package com.pxmeta.party.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.pxmeta.common.core.redis.RedisCache;
import com.pxmeta.common.exception.ServiceException;
import com.pxmeta.party.entity.*;
import com.pxmeta.party.entity.dto.ActivityAdAstraDTO;
import com.pxmeta.party.entity.vo.ActivityAdAstraDataHistoryVO;
import com.pxmeta.party.entity.vo.ActivityAdAstraDataStatisticsItemVO;
import com.pxmeta.party.entity.vo.ActivityAdAstraDataStatisticsVO;
import com.pxmeta.party.mapper.ActivityAdAstraMapper;
import com.pxmeta.party.service.*;
import com.pxmeta.user.entity.User;
import com.pxmeta.user.service.IUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.compress.utils.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@RequiredArgsConstructor
@Slf4j
public class ActivityAdAstraServiceImpl extends ServiceImpl<ActivityAdAstraMapper, ActivityAdAstra> implements IActivityAdAstraService {

    @Autowired
    private IUserService userService;

    @Autowired
    private IPartyService partyService;

    @Autowired
    private IGiftService giftService;

    @Autowired
    private IActivityAdAstraRecordService activityAdAstraRecordService;

    @Autowired
    private IActivityAdAstraUserRecordService activityAdAstraUserRecordService;

    @Autowired
    private ITurntableNumberService turntableNumberService;

    @Autowired
    private ILotteryLuckyUserService lotteryLuckyUserService;

    @Autowired
    private RedisCache redisCache;

    @Override
    public ActivityAdAstra confirmDispatch(Long userId, List<ActivityAdAstraDTO> dtos) {

        //获取结束时间
        Long endTimeMillis = redisCache.getCacheObject("countdown_time");
        double l = (double)(endTimeMillis - System.currentTimeMillis()) / 1000;
        //如果结束时间小于10秒，则无法继续下注
        if (l<8){
            throw new ServiceException("当前已结束，请下一轮再派遣！");
        }
        TurntableNumber turntableNumber = turntableNumberService.getTurntableNumber(7);
        //设置已抽期数+1
        turntableNumber.setLotteryCount(turntableNumber.getLotteryCount() +1);
        ActivityAdAstraRecord currentRecord = activityAdAstraRecordService.getCurrentRecord();



        List<Long> ids = dtos.stream().map(ActivityAdAstraDTO::getId).collect(Collectors.toList());
        if (ids.isEmpty()){
            return null;
        }
        Long successId = currentRecord.getSuccessId();
        log.info("开始检查是否中奖,奖励id:{}",successId);
        //检查是否中奖
        ActivityAdAstra success = this.getById(successId);

        BigDecimal consumeNumber = turntableNumber.getConsumeNumber();
        BigDecimal giftNumber = turntableNumber.getGiftNumber();
        int totalCount = dtos.stream().mapToInt(ActivityAdAstraDTO::getCount).sum();

//        User user = userService.getById(userId);
        userService.subAdAstraBalance(userId, totalCount);

        //总消费金额
        long consumePrice = totalCount * 500L;
        consumeNumber = consumeNumber.add(BigDecimal.valueOf(consumePrice));
        turntableNumber.setConsumeNumber(consumeNumber);
        activityAdAstraUserRecordService.saveRecord(userId, currentRecord.getId(), successId, dtos);
        turntableNumberService.updateById(turntableNumber);
        return success;
    }

//    /**
//     * 重置奖励
//     */
//    private void resetReward(BigDecimal giftNumber){
//        ActivityAdAstraRecord currentRecord = activityAdAstraRecordService.getCurrentRecord();
//
//        //平台亏损
//        if (currentRecord.getSuccessId().equals(2L)){
//            currentRecord.setSuccessId(3L);
//        }else {
//            currentRecord.setSuccessId(2L);
//        }
//        activityAdAstraRecordService.updateById(currentRecord);
//
//        log.info("平台计算亏损开始重置奖励,currentRecordId:{}...",currentRecord.getId());
//        //变更奖励
//        ActivityAdAstra success = this.getById(currentRecord.getSuccessId());
//        log.info("平台计算亏损开始重置奖励...成功奖励：{}",success);
//        //重置其他人所有奖励
//        List<LotteryLuckyUser> otherLuckyUsers = lotteryLuckyUserService.getByRecordId(currentRecord.getId());
//        log.info("平台计算亏损开始重置奖励...重置其他人所有奖励,需要重置的数量{}",otherLuckyUsers.size());
//        List<LotteryLuckyUser> updateList = Lists.newArrayList();
//
//        for (LotteryLuckyUser otherLuckyUser : otherLuckyUsers) {
//            Integer otherCount = otherLuckyUser.getCount();
//            int coins = otherCount * success.getMagnification() * 500;
//            giftNumber = giftNumber.subtract(BigDecimal.valueOf(otherLuckyUser.getPrice())).add(BigDecimal.valueOf(coins));
//            otherLuckyUser.setPrice(coins);
//            otherLuckyUser.setContent(null);
//            updateList.add(otherLuckyUser);
//        }
//
//        if (!updateList.isEmpty()){
//            lotteryLuckyUserService.updateBatchById(updateList);
//        }
//
//        ActivityAdAstra finalSuccess = success;
//        Optional<ActivityAdAstraDTO> optional = dtos.stream().filter(d -> d.getId().equals(finalSuccess.getId())).findFirst();
//        if (optional.isPresent()){
//            ActivityAdAstraDTO dto2 = optional.get();
//            count = dto2.getCount();
//            lotteryLuckyUser.setCount(count);
//            coins = count  * success.getMagnification() * 500;
//            lotteryLuckyUser.setPrice(coins);
//            lotteryLuckyUser.setGiftId(dto2.getId().intValue());
//            lotteryLuckyUser.setContent("恭喜 "+ nickname + " "+"获得"+ count +"探险值");
//
//            giftNumber = giftNumber.add(BigDecimal.valueOf(coins));
//            turntableNumber.setGiftNumber(giftNumber);
//        }else {
//            turntableNumberService.updateById(turntableNumber);
//            return success;
//        }
//
//
//    }

    @Override
    public List<ActivityAdAstra> getStarList(Long userId) {
        Long recordId = activityAdAstraRecordService.getCurrentRecord().getId();
        List<ActivityAdAstraUserRecord> records = activityAdAstraUserRecordService.getByRecordId(recordId,userId);

        LambdaQueryWrapper<ActivityAdAstra> wrapper = Wrappers.lambdaQuery();
        wrapper.orderByDesc(ActivityAdAstra::getSort);
        List<ActivityAdAstra> list = this.list(wrapper);
        for (ActivityAdAstra activityAdAstra : list) {
            for (ActivityAdAstraUserRecord record : records) {
                if (activityAdAstra.getId().equals(record.getStarId())){
                    activityAdAstra.setCurrentCount(record.getCount());
                }
            }
        }

        return list;
    }

    @Override
    public IPage<ActivityAdAstra> getStarList(Integer page, Integer size) {
        return this.page(new Page<>(page,size));
    }

    @Override
    @Transactional(rollbackFor = ServiceException.class)
    public void buyShip(Long userId, Integer count, String partyId) {
        User user = userService.getById(userId);
        Party party = partyService.getById(partyId);
        User targetUser = userService.getById(party.getUserId());
        Gift gift = giftService.getByType(10);
        giftService.give(userId,Long.parseLong(targetUser.getUsername()),gift.getId(),Long.parseLong(partyId),10,count);
        Integer adAstraBalance = user.getAdAstraBalance();
        adAstraBalance += count;
        user.setAdAstraBalance(adAstraBalance);
        userService.updateById(user);
        //扣减余额
        userService.subBalance(userId,count*500);
    }

    @Override
    public List<ActivityAdAstraDataHistoryVO> getDataList(Integer page, Integer size) {

        LambdaQueryWrapper<ActivityAdAstraRecord> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(ActivityAdAstraRecord::getStatus,1);
        wrapper.orderByDesc(ActivityAdAstraRecord::getCreateTime);
        Page<ActivityAdAstraRecord> result = activityAdAstraRecordService.page(new Page<>(page, size), wrapper);

        List<ActivityAdAstraRecord> records = result.getRecords();

        List<ActivityAdAstraDataHistoryVO> finalList = Lists.newArrayList();

        for (ActivityAdAstraRecord record : records) {
            ActivityAdAstraDataHistoryVO vo = new ActivityAdAstraDataHistoryVO();
            Long successId = record.getSuccessId();
            ActivityAdAstra adAstra = this.getById(successId);
            //获取参与人数
            List<ActivityAdAstraUserRecord> userRecords = activityAdAstraUserRecordService.getByRecordId(record.getId());
            int totalUser = userRecords.stream().map(ActivityAdAstraUserRecord::getUserId).collect(Collectors.toSet()).size();
            List<ActivityAdAstraUserRecord>  successUsers = userRecords.stream().filter(u -> u.getStatus() == 1).collect(Collectors.toList());
            int sum = successUsers.stream().mapToInt(ActivityAdAstraUserRecord::getRewardPrice).sum();
            int successUserCount = successUsers.stream().map(ActivityAdAstraUserRecord::getUserId).collect(Collectors.toSet()).size();
            vo.setFlyCount(totalUser);
            vo.setCreateTime(record.getCreateTime());
            vo.setMagnification(adAstra.getMagnification());
            vo.setName(adAstra.getName());
            vo.setId(record.getId());
            vo.setLuckyUserCount(successUserCount);
            vo.setGiftPrice(sum);
            finalList.add(vo);
        }

        return finalList;
    }

    @Override
    public List<ActivityAdAstra> getStarOverdueCount() {

        LambdaQueryWrapper<ActivityAdAstra> wrapper = Wrappers.lambdaQuery();
        List<ActivityAdAstra> list = this.list(wrapper);

        LambdaQueryWrapper<ActivityAdAstraRecord> recordWrapper = Wrappers.lambdaQuery();
        recordWrapper.eq(ActivityAdAstraRecord::getStatus, 1)
                .orderByDesc(ActivityAdAstraRecord::getCreateTime)
                .last("limit 1000");
        List<ActivityAdAstraRecord> recordList = activityAdAstraRecordService.list(recordWrapper);

        for (ActivityAdAstra activityAdAstra : list) {
            //获取逾期数
            for (int i = 0; i < recordList.size(); i++) {
                ActivityAdAstraRecord record = recordList.get(i);
                if (activityAdAstra.getId().equals(record.getSuccessId())){
                    activityAdAstra.setOverdueCount(i);
                    break;
                }
            }

        }

        return list;
    }

    @Override
    public List<ActivityAdAstraDataStatisticsVO> getDataStatistics() {
        List<ActivityAdAstra> list = this.list();

        QueryWrapper<ActivityAdAstraRecord> query = Wrappers.query();

        List<ActivityAdAstraRecord> hourRecordList = activityAdAstraRecordService.getHourRecordList();

        List<ActivityAdAstraRecord> todayRecordList = activityAdAstraRecordService.getTodayRecordList();



        List<ActivityAdAstraRecord> lastDayRecordList = activityAdAstraRecordService.getLastDayRecordList();

        List<ActivityAdAstraDataStatisticsVO> finalList = Lists.newArrayList();

        for (ActivityAdAstra activityAdAstra : list) {
            ActivityAdAstraDataStatisticsVO vo = new ActivityAdAstraDataStatisticsVO();
            long hourCount = hourRecordList.stream().filter(r -> r.getSuccessId().equals(activityAdAstra.getId())).count();
            Double hourProbability = BigDecimal.valueOf(((double) hourCount/hourRecordList.size())*100).setScale(2, RoundingMode.HALF_UP).doubleValue();
            vo.setHourProbability(hourProbability);
            vo.setHourCount((int) hourCount);

            vo.setMagnification(activityAdAstra.getMagnification());
            vo.setId(activityAdAstra.getId());
            vo.setName(activityAdAstra.getName());

            long todayCount = todayRecordList.stream().filter(t->t.getSuccessId().equals(activityAdAstra.getId())).count();
            vo.setTodayCount((int)todayCount);

            long lastDayCount = lastDayRecordList.stream().filter(l->l.getSuccessId().equals(activityAdAstra.getId())).count();
            vo.setLastDayCount((int)lastDayCount);
            double lastDayProbability = BigDecimal.valueOf(((double) lastDayCount/lastDayRecordList.size())*100).setScale(2, RoundingMode.HALF_UP).doubleValue();
            vo.setLastDayProbability(lastDayProbability);


            for (int i = 0; i < todayRecordList.size(); i++) {
                ActivityAdAstraRecord record = todayRecordList.get(i);
                if (record.getSuccessId().equals(activityAdAstra.getId())){
                    vo.setLateCount(i);
                    break;
                }
            }
            finalList.add(vo);
        }

        return finalList;
    }

    @Override
    public List<ActivityAdAstraDataStatisticsItemVO> getDataStatisticsDetail(Long id) {
        List<ActivityAdAstraDataStatisticsItemVO> list = baseMapper.getDataStatisticsDetail(id);
        for (ActivityAdAstraDataStatisticsItemVO vo : list) {
            double probability = BigDecimal.valueOf((double) vo.getCount()*100 / 60).setScale(2, RoundingMode.HALF_UP).doubleValue();
            vo.setProbability(probability);
        }
        return list;
    }
}
